package cn.mazexal.examapi.controller;

import cn.mazexal.examapi.common.anno.PermitGuest;
import cn.mazexal.examapi.common.models.*;
import cn.mazexal.examapi.models.db.FinOrderDO;
import cn.mazexal.examapi.models.db.FinOrderPayDO;
import cn.mazexal.examapi.models.enums.PayStatusEnum;
import cn.mazexal.examapi.models.form.AppleyPayVerifyForm;
import cn.mazexal.examapi.models.form.VipOrderForm;
import cn.mazexal.examapi.models.qry.IDQry;
import cn.mazexal.examapi.models.qry.OrderQry;
import cn.mazexal.examapi.models.redisKeys.RedisCommonKey;
import cn.mazexal.examapi.models.redisKeys.RedisOrderKey;
import cn.mazexal.examapi.models.vo.AddVipOrderRes;
import cn.mazexal.examapi.models.vo.FinOrderVO;
import cn.mazexal.examapi.models.vo.SingleResVO;
import cn.mazexal.examapi.models.vo.VipPriceVO;
import cn.mazexal.examapi.services.CommonService;
import cn.mazexal.examapi.services.OrderService;
import cn.mazexal.examapi.services.RedisService;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author: Mazexal
 * Date: 2025/6/28
 */
@RestController
@Tag(name = "order", description = "订单接口")
@RequestMapping("/order")
@Slf4j
public class OrderController extends BaseController {

    @Resource
    private OrderService orderService;

    @Resource
    private CommonService commonService;

    @Resource
    private RedisService redisService;

    @PermitGuest
    @PostMapping("/getVipPriceConfig")
    @Schema(description = "获取VIP时长价格配置")
    public MultiResponse<VipPriceVO> getVipPriceConfig() {
        Long channelId = getChannelId();
        if (channelId == 0) {
            throw new BizException(new CustomerError("500", "不支持的渠道"));
        }
        return MultiResponse.of(commonService.getVipPriceConfigList(channelId));
    }

    @PostMapping("/addVipOrder")
    @Schema(description = "添加购买VIP订单")
    public SingleResponse<AddVipOrderRes> addVipOrder(@RequestBody VipOrderForm orderForm) {
        String configStr = orderForm.getVipPriceConfigId();
        Long channelId = getChannelId();
        Long userId = getUserId();
        if (channelId == 0) {
            throw new BizException(new CustomerError("500", "不支持的渠道"));
        }
        Integer payWay = orderForm.getPayWay();
        String ip = getIp();
        String key = RedisOrderKey.getUserOrderKey(userId);
        if (redisService.tryLock(key, RedisCommonKey.keyValue, 5, TimeUnit.SECONDS)) {
            AddVipOrderRes res = orderService.addVipOrder(userId, channelId, configStr, payWay, ip);
            redisService.releaseLock(key, RedisCommonKey.keyValue);
            return SingleResponse.of(res);
        }
        return SingleResponse.error(new CustomerError("500", "请勿重复提交"));
    }

    // todo 需要写单元测试
    // 为了防止多次支付, 所以必定是先创建订单再支付的.
    @PostMapping("/getPayParam")
    public SingleResponse<SingleResVO<String>> getPayParam(@RequestBody IDQry idQry) throws Exception {
        // 查询订单是否存在
        FinOrderDO finOrderDO = orderService.checkOrder(idQry.getId());
        // 说明之前已经创建了支付订单
        if (StringUtils.isNotBlank(finOrderDO.getPayParams())) {
            SingleResVO<String> res = new SingleResVO<>(finOrderDO.getPayParams());
            return SingleResponse.of(res);
        }
//        // 判断是否已创建支付订单
//        orderService.checkOrderPay(idQry.getId());
        // 返回支付参数.
        String payParam = orderService.addOrderPayAndPayParam(finOrderDO);
        SingleResVO<String> res = new SingleResVO<>(payParam);
        return SingleResponse.of(res);
    }

    @PostMapping("/getPayStatus")
    @Schema(description = "获取支付状态")
    public SingleResponse<SingleResVO<PayStatusEnum>> getPayStatus(@RequestBody IDQry idQry) {
        PayStatusEnum payStatus = orderService.getPayStatus(idQry.getId());
        SingleResVO<PayStatusEnum> res = new SingleResVO<>(payStatus);
        return SingleResponse.of(res);
    }

    @PostMapping("/getUserOrderList")
    @Schema(description = "获取用户订单列表")
    public PagedResponse<FinOrderVO> getUserOrderList(OrderQry qry){
        Long userId = getUserId();
        qry.setUserId(userId);
        return PagedResponse.of(orderService.getOrderList(qry));
    }

    @PostMapping("/applePayVerify")
    @Schema(description = "苹果支付校验, 这里只检查了传入数据是否符合苹果加密, 并且绑定了外部订单ID, 实际上没有做发放VIP处理")
    public SingleResponse<SingleResVO<Boolean>> applePayVerify(@RequestBody AppleyPayVerifyForm payParams) {
        Long userId = getUserId();
        String key = RedisOrderKey.getUserAppleyVerifyKey(userId, payParams.getOrderId());
        if (redisService.tryLock(key, RedisCommonKey.keyValue, 5, TimeUnit.SECONDS)) {
            boolean res = false;
            try {
                res = orderService.applePayVerify(userId, payParams);
            } catch (Exception e) {
                log.error("applePayVerify error", e);
                return SingleResponse.error(new CustomerError("500", "校验出错, 请稍后重试"));
            } finally {
                redisService.releaseLock(key, RedisCommonKey.keyValue);
            }
            SingleResVO<Boolean> resVO = new SingleResVO<>(res);
            return SingleResponse.of(resVO);
        }
        return SingleResponse.error(new CustomerError("500", "请勿重复提交"));
    }

}
